<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        class DBNode {
            constructor(data) {
                this.data = data;
                this.prev = null;
                this.next = null;

            }
        }

        class DBLinkedList {
            constructor() {
                this.head = null;
                this.tail = null;
                this.count = 0;
            }

            push(element) {
                let node = new DBNode(element);
                if (this.size() == 0) {
                    // 如果size为0, 则代表当前链表为空, 那么无论头还是尾肯定都是这个节点了
                    this.head = node;
                    this.tail = node;
                } else {
                    // 反之如果size不为0, 那就把尾部的next指向这个节点, 顺便让这个节点的prev指向尾部, 最后在让尾部指向这个节点
                    this.tail.next = node;
                    node.prev = this.tail;
                    this.tail = node;
                }
                this.count++;
            }

            // 在任意位置插入一个节点
            insert(element, index) {
                // 首先index要符合规定
                if (index >= 0 && index <= this.count) {
                    let node = new DBNode(element);
                    let current = this.head;

                    // 如果插入位置是最开始
                    if (index == 0) {
                        if (this.head == null) {
                            this.head = node;
                            this.tail = node;
                        } else {
                            node.next = this.head;
                            this.head.prev = node;
                            this.head = node;
                        }
                    }
                    // 如果插入位置就是最后一个
                    else if (index == this.count) {
                        current = this.tail;
                        current.next = node;
                        node.prev = current;
                        this.tail = node;
                    }
                    // 既不是头也不是尾, 那就要遍历到目标位置再进行操作了
                    else {
                        // 注意, current是要插入位置原本的节点, 所以我们要创建一个变量保存当前节点的prev。
                        current = this.getNodeAt(index);
                        let prev = current.prev;

                        // 思路很简单, 让前面那个节点的next指向node, 再让node的prev指回去。后面node和current的关系亦是如此
                        prev.next = node;
                        node.prev = prev;
                        node.next = current;
                        current.prev = node;
                    }

                    this.count++;
                    return true;
                }
                return false;
            }

            size() {
                return this.count;
            }

            getNodeAt(index) {
                if (index >= 0 && index < this.count) {
                    let current = this.head;
                    for (let i = 0; i < index; i++) {
                        current = current.next;
                    }
                    return current;
                }
            }

            removeAt(index) {
                if (index >= 0 && index < this.count) {
                    let current = this.head;
                    if (index == 0) {
                        this.head = current.next;
                        this.head.prev = null;
                    } else if (index == this.count - 1) {
                        current = this.tail;
                        this.tail = current.prev;
                        this.tail.next = null;
                    } else {

                    }
                    this.count--;
                    return current.data;
                }
                return false;
            }

            getHead(){
                return this.head;
            }

            getTail(){
                return this.tail;
            }
        }

        let list = new DBLinkedList();
    </script>
</body>

</html>